package cz.muni.fi.pa165.machineryrental.weblayer.controllers;

import cz.muni.fi.pa165.machineryrental.dto.MachineDTO;
import cz.muni.fi.pa165.machineryrental.dto.RentalDTO;
import cz.muni.fi.pa165.machineryrental.dto.RevisionDTO;
import cz.muni.fi.pa165.machineryrental.weblayer.utils.Utils;
import cz.muni.fi.pa165.machineryrental.weblayer.validator.MachineValidator;
import cz.muni.fi.pa165.machineryrental.service.MachineService;
import cz.muni.fi.pa165.machineryrental.service.RentalService;
import cz.muni.fi.pa165.machineryrental.service.RevisionService;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author David Katuscak, 359273
 */
@Controller
public class MachineController {

    @Autowired
    private MachineService machineService;
    @Autowired
    private RentalService rentalService;
    @Autowired
    private RevisionService revisionService;
    @Autowired
    private MachineValidator machineValidator;
    String kk1;
    String kk2;

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        SimpleDateFormat sf = Utils.getCurrentSimpleDateFormat();
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sf, true));
        webDataBinder.setValidator(this.machineValidator);
    }

    @RequestMapping("/machine/index")
    public ModelAndView index() {

        List<MachineDTO> machines = machineService.findAll();

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("machines", machines);

        return new ModelAndView("/machine/index.jsp", "model", model);
    }

    @RequestMapping(value = "/machine/index", method = RequestMethod.POST)
    public ModelAndView index(String searchBy, String search, Map<String, Object> map,
            HttpServletRequest request) {

        Map<String, Object> model = new HashMap<String, Object>();
        List<MachineDTO> machines = new ArrayList<MachineDTO>();

        if (searchBy != null && !searchBy.equals("")) {
            if (searchBy.equals("brand")) {
                machines = machineService.findByBrand(search);
            } else if (searchBy.equals("code")) {
                machines.add(machineService.findByCode(search));
            } else if (searchBy.equals("model")) {
                machines = machineService.findByModel(search);
            }
        }

        model.put("machines", machines);
        model.put("search", search);
        model.put("searchBy", searchBy);

        return new ModelAndView("/machine/index.jsp", "model", model);
    }

    private Map<String, Object> prepareDataForDetailPage(long id) {
        MachineDTO machine = this.machineService.getById(id);
        List<RentalDTO> rentals = this.rentalService.findByMachine(machine);
        List<RevisionDTO> revisions = this.revisionService.findByMachine(machine);

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("machine", machine);
        model.put("rentals", rentals);
        model.put("revisions", revisions);
        model.put("rentalsNumber", rentals.size());
        model.put("revisionsNumber", revisions.size());

        return model;
    }

    private Map<String, Object> prepareDataForDetailPage(long id, Date startDate, Date endDate) {
        MachineDTO machine = this.machineService.getById(id);
        List<RentalDTO> rentals = this.rentalService.findByMachine(machine);
        List<RevisionDTO> revisions = this.revisionService.findByInterval(startDate, endDate, machine);

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("machine", machine);
        model.put("rentals", rentals);
        model.put("revisions", revisions);
        model.put("rentalsNumber", rentals.size());
        model.put("revisionsNumber", revisions.size());

        return model;
    }

    @RequestMapping("/machine/detail/{id}")
    public ModelAndView detail(@PathVariable long id) {

        Map<String, Object> model = prepareDataForDetailPage(id);

        return new ModelAndView("/machine/detail.jsp", "model", model);
    }

    @RequestMapping(value = "/machine/detail/{id}", method = RequestMethod.POST)
    public ModelAndView detail(@PathVariable long id, Date startDate, Date endDate, Map<String, Object> map,
            HttpServletRequest request) {

        if (startDate == null) {
            Calendar cal = Calendar.getInstance();
            cal.set(1900, 1, 1);
            startDate = cal.getTime();
        }
        if (endDate == null) {
            endDate = new Date();
        }

        Map<String, Object> model = prepareDataForDetailPage(id, startDate, endDate);

        return new ModelAndView("/machine/detail.jsp", "model", model);
    }

    @RequestMapping("/machine/add")
    public ModelAndView add() {
        ModelAndView mav = new ModelAndView("/machine/add.jsp", "machine", new MachineDTO());
        return mav;
    }

    @RequestMapping(value = "/machine/add", method = RequestMethod.POST)
    public ModelAndView add(@Valid @ModelAttribute("machine") MachineDTO machine, BindingResult result) {

        if (result.hasErrors()) {
            return new ModelAndView("/machine/add.jsp");
        }

        this.machineService.create(machine);

        ModelAndView mav = new ModelAndView();
        mav.setViewName("redirect:/machine/detail/" + machine.getId());
        return mav;
    }

    @RequestMapping(value = "/machine/edit", method = RequestMethod.POST)
    public ModelAndView edit(@Valid @ModelAttribute("machine") MachineDTO machine, BindingResult result) {

        if (result.hasErrors()) {
            return new ModelAndView("/machine/edit.jsp", "machine", machine);
        }

        this.machineService.update(machine);
        return new ModelAndView("redirect:/machine/detail/" + machine.getId());
    }

    @RequestMapping(value = "/machine/edit/{id}", method = RequestMethod.GET)
    public String edit(@PathVariable long id, Model model) {

        MachineDTO machine = this.machineService.getById(id);
        if (machine == null) {
            model.addAttribute("machine", null);
            return "/machine/edit.jsp";
        }

        model.addAttribute("machine", machine);
        model.addAttribute("dateformat", Utils.getCurrentSimpleDateFormat().toPattern());

        return "/machine/edit.jsp";
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping("/machine/remove/{id}")
    public ModelAndView remove(@PathVariable long id) {

        MachineDTO machine = this.machineService.getById(id);
        machineService.remove(machine);
        return new ModelAndView("redirect:/machine/index");
    }
}
